{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import torch\n",
    "import torch.utils.data\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "import torch.optim as optim\n",
    "from torch.autograd import Variable\n",
    "from torchvision import datasets, transforms\n",
    "from torchvision.utils import make_grid , save_image"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "def show_adn_save(file_name,img):\n",
    "    npimg = np.transpose(img.numpy(),(1,2,0))\n",
    "    f = \"./%s.png\" % file_name\n",
    "    plt.imshow(npimg)\n",
    "    plt.imsave(f,npimg)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "class RBM(nn.Module):\n",
    "    def __init__(self,\n",
    "                 n_vis=784,\n",
    "                 n_hin=500,\n",
    "                 k=5):\n",
    "        super(RBM, self).__init__()\n",
    "        self.W = nn.Parameter(torch.randn(n_hin,n_vis)*1e-2)\n",
    "        self.v_bias = nn.Parameter(torch.zeros(n_vis))\n",
    "        self.h_bias = nn.Parameter(torch.zeros(n_hin))\n",
    "        self.k = k\n",
    "    \n",
    "    def sample_from_p(self,p):\n",
    "        return F.relu(torch.sign(p - Variable(torch.rand(p.size()))))\n",
    "    \n",
    "    def v_to_h(self,v):\n",
    "        p_h = F.sigmoid(F.linear(v,self.W,self.h_bias))\n",
    "        sample_h = self.sample_from_p(p_h)\n",
    "        return p_h,sample_h\n",
    "    \n",
    "    def h_to_v(self,h):\n",
    "        p_v = F.sigmoid(F.linear(h,self.W.t(),self.v_bias))\n",
    "        sample_v = self.sample_from_p(p_v)\n",
    "        return p_v,sample_v\n",
    "        \n",
    "    def forward(self,v):\n",
    "        pre_h1,h1 = self.v_to_h(v)\n",
    "        \n",
    "        h_ = h1\n",
    "        for _ in range(self.k):\n",
    "            pre_v_,v_ = self.h_to_v(h_)\n",
    "            pre_h_,h_ = self.v_to_h(v_)\n",
    "        \n",
    "        return v,v_\n",
    "    \n",
    "    def free_energy(self,v):\n",
    "        vbias_term = v.mv(self.v_bias)\n",
    "        wx_b = F.linear(v,self.W,self.h_bias)\n",
    "        hidden_term = wx_b.exp().add(1).log().sum(1)\n",
    "        return (-hidden_term - vbias_term).mean()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "batch_size = 64\n",
    "train_loader = torch.utils.data.DataLoader(\n",
    "    datasets.MNIST('../data', train=True, download=False,\n",
    "                   transform=transforms.Compose([\n",
    "                       transforms.ToTensor()\n",
    "                   ])),\n",
    "    batch_size=batch_size)\n",
    "\n",
    "test_loader = torch.utils.data.DataLoader(\n",
    "    datasets.MNIST('../data', train=False, transform=transforms.Compose([\n",
    "                       transforms.ToTensor()\n",
    "                   ])),\n",
    "    batch_size=batch_size)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "rbm = RBM(k=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "train_op = optim.SGD(rbm.parameters(),0.1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-8.46589652511\n",
      "-6.75963076854\n",
      "-4.64520969676\n",
      "-3.23767424951\n",
      "-2.21390001504\n",
      "-1.53582236609\n",
      "-1.07248666597\n",
      "-0.743972908459\n",
      "-0.445539202009\n",
      "-0.264593714082\n"
     ]
    }
   ],
   "source": [
    "for epoch in range(10):\n",
    "    loss_ = []\n",
    "    for _, (data,target) in enumerate(train_loader):\n",
    "        data = Variable(data.view(-1,784))\n",
    "        sample_data = data.bernoulli()\n",
    "        \n",
    "        v,v1 = rbm(sample_data)\n",
    "        loss = rbm.free_energy(v) - rbm.free_energy(v1)\n",
    "        loss_.append(loss.data[0])\n",
    "        train_op.zero_grad()\n",
    "        loss.backward()\n",
    "        train_op.step()\n",
    "    \n",
    "    print np.mean(loss_)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x10b337710>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "show_adn_save(\"real\",make_grid(v.view(32,1,28,28).data))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\nSUVORK5CYII=\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x10f960bd0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "show_adn_save(\"generate\",make_grid(v1.view(32,1,28,28).data))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
